
import ucigame.*;

//import java.util.*;
//import java.math.*;


public class SpaceMission extends Ucigame
{
	//Set up ship
	Sprite ship;
	int shipRotation;
	final int shipCenterX = 30;
	final int shipCenterY = 60;
	int[] shipAtStartX = {0,0,0,0,0,0,0,0,0,0};
	int[] shipAtStartY = {0,0,0,0,0,0,0,0,0,0};
	int shield;
	int lives;
	Sprite laserbeam;
	int laserRotation;
	final int laserCenterX = 21;
	final int laserCenterY = 10;
	boolean laserExists;
	boolean laserTimeOut;
	Sprite gun;
	Sprite rearFire;
	Sound laserSound;
	Sound openingLoop;
	Sound thrusterSound;
	boolean thrusterSoundActive;
	
	Sound track1;
	Sound track2;
	Sound track3;
	Sound track4;
	Sound track5;
	Sound track6;
	Sound track7;
	
	
	int currentTrack;
	
	//Set up level variables
	int currentLevel;
	int lastLevel;
	int survivalTime;
	boolean success;
	long start_time;
	boolean gameover;	
	
	//Set up baddies
	Sprite spinningC;
	int numHitsToDestroyRock;
	Sprite rock1;
	Sprite rock2;
	Sprite rock3;
	Sprite rock4;
	Sprite rock5;
	int rocklife1;
	int rocklife2;
	int rocklife3;
	int rocklife4;
	int rocklife5;
	Sprite enemy1;
	Sprite enemy2;
	Sprite enemy3;
	
	Sprite enemyGun1;
	Sprite enemyLaser1;
	int enemylife1;
	boolean enemyLaser1Exists;
	boolean enemyLaser1TimeOut;
	int enemyLaser1Rotation;
	final int enemyLaser1CenterX = 10;
	final int enemyLaser1CenterY = 10;
	
	//Set up HUD
    Sprite display;
    Sprite victory;
    Sprite failure;
    
    //Set up backgrounds
    Sprite title;
    Sprite enterToStart;
    
    //Set up final portal
    //SET UP EACH LEVEL POSITION HERE!
    Sprite portal;
    double portalRotation;
    final int portalCenterX = 42;
    final int portalCenterY = 48;
	int[] portalX = {700,700,400,700,700,700,700,700,700,700};
	int[] portalY = {415,0,250,415,0,415,0,0,0,0};
	int[] rock1X = {650,650,600,695,404,91, 650,650,650,650};
	int[] rock1Y = {200,200,300,330,82,449, 200,200,200,200};
	int[] rock2X = {500,500,290,600,238,216, 500,500,500,500};
	int[] rock2Y = {20,20,230,220,156,327, 20,20,20,20};
	int[] rock3X = {100,100,90,400,578,414, 100,100,100,100};
	int[] rock3Y = {100,100,400,255,200,274, 100,100,100,100};
	int[] rock4X = {200,200,158,600,300,589, 200,200,200,200};
	int[] rock4Y = {400,400,158,150,433,127, 400,400,400,400};
	int[] rock5X = {300,300,700,100,300,170, 300,300,300,300};
	int[] rock5Y = {300,300,0,200,300,607,120, 300,300,300};

	public void gameover()
	{
		gameover = true;
		currentLevel = 11;
		setupCurrentLevel();
	}
    
    public void setup()
    {
    	window.size(844,580);
		window.title("SPACE MISSION");
		framerate(30);
		window.showFPS();
		
		currentLevel = 0;//title screen;
		lives = 3;
		//lastLevel = 10;
		gameover = false;
		
		//make ship
    	ship = makeSprite(getImage("ship02.png",0,255,0));
    	
    	
		// set up 
		// this sprite lets me easily find the right spot to fire the laser
		// from, no matter the ship's orientation.
		gun = makeSprite(getImage("blank1.png", 255, 0, 0));
		ship.pin(gun, 85, 40);
		laserbeam = makeSprite(getImage("laser.png", 0, 0, 255));
		laserExists = false;
		laserTimeOut = false;
		laserRotation = 0;
		
		//set up rear fire
		rearFire = makeSprite(25, 12);
		rearFire.addFrames(
				getImage("Thrust_FINAL.png", 0, 255, 0),
				0, 0,
				25, 0,
				0, 12,
				25, 12);
		rearFire.framerate(10);
		
		// pin fire to ship.
		ship.pin(rearFire, -22, 52);
		rearFire.hide();
		
    	//make portal
    	portal = makeSprite(getImage("portal.png",0,0,255));
    	portalRotation = 0;
    	
    	startTimer("portalRotator",10);
    	
    	
    	//make obstacles
    	rock1 = makeSprite(getImage("rock.png", 255, 255, 255));
    	rock2 = makeSprite(getImage("rock.png", 255, 255, 255));
    	rock3 = makeSprite(getImage("rock.png", 255, 255, 255));
    	rock4 = makeSprite(getImage("rock.png", 255, 255, 255));
    	rock5 = makeSprite(getImage("rock.png", 255, 255, 255));
    	enemy1 = makeSprite(getImage("milleniumfalcon.gif", 255,255,255));
    	enemy2 = makeSprite(getImage("ship_new3.jpg",0, 255, 1));
    	enemy3 = makeSprite(getImage("star_digitized3.jpg", 0, 255, 1));
    	
    	//Enemy Guns
    	enemyGun1 = makeSprite(getImage("blank1.png", 255, 0, 0));
		ship.pin(enemyGun1, 85, 40);
		enemyLaser1 = makeSprite(getImage("shot.png", 0, 0, 255));
		enemyLaser1Exists = false;
		enemyLaser1TimeOut = false;
		enemyLaser1Rotation = 0;
    	
		//Load sounds
		laserSound = getSound("laser.mp3");
		thrusterSound = getSound("Rocket_Away.mp3");
		openingLoop = getSound("Opening_Loop.mp3");
		track1 = getSound("track1.mp3");
		track2 = getSound("track2.mp3");
		track3 = getSound("track3.mp3");
		track4 = getSound("track4.mp3");
		track5 = getSound("track5.mp3");
		track6 = getSound("track6.mp3");
		track7 = getSound("track7.mp3");
		thrusterSoundActive = false;
		
		openingLoop.loop();
		
		currentTrack = 0;
		
    	//titleScreen();
    	setupCurrentLevel();
    }
    
    public void portalRotatorTimer()
    {
        portalRotation += 360/350;
    }
    
	private void setupCurrentLevel()
	{
		//Setup Music
		if(currentLevel == 1 && currentTrack != 3)
		{
			openingLoop.stop();
			track3.loop();
			currentTrack = 3;
		}

		if(currentLevel == 4 && currentTrack != 4)
		{
			track3.stop();
			track4.loop();
		}
		
		if(currentLevel == 6 && currentTrack != 5)
		{
			track4.stop();
			track5.loop();
		}

		if(currentLevel == 7 && currentTrack != 6)
		{
			track5.stop();
			track6.loop();
		}
	
		if(currentLevel == 8 && currentTrack != 7)
		{
			track6.stop();
			track7.loop();
		}
		
		
		
		if(currentLevel != 11)
		{	

			Image bg = getImage("bg/" + currentLevel + ".png");
			canvas.background(bg);
	
			ship.position(shipAtStartX[currentLevel], shipAtStartY[currentLevel]);
			shipRotation = 0;
	
			portal.position(portalX[currentLevel], portalY[currentLevel]);
			//portalSuccess.hide();
			
			//position obstacles
			rock1.position(rock1X[currentLevel], rock1Y[currentLevel]);
			rock2.position(rock2X[currentLevel], rock2Y[currentLevel]);
			rock3.position(rock3X[currentLevel], rock3Y[currentLevel]);
			rock4.position(rock4X[currentLevel], rock4Y[currentLevel]);
			rock5.position(rock5X[currentLevel], rock5Y[currentLevel]);
			enemy1.position(200, 200);
			enemy2.position(300, 400);
			enemy3.position(300, 500);
			
			rock1.show();
			rock2.show();
			rock3.show();
			rock4.show();
			rock5.show();
			
			enemy1.motion(10, 4);
			enemy1.show();
			enemy2.motion(10, -5);
			enemy2.show();
			enemy3.motion(5, -5);
			enemy3.show();
			
			numHitsToDestroyRock = 5;// a little buggy... not exactly 3 because the laser stops on the rock for a millisecond and causes an extra one to go down...
	    	//5 actually means 3
			//4 means 2
			
	    	rocklife1 = numHitsToDestroyRock;
	    	rocklife2 = numHitsToDestroyRock;
	    	rocklife3 = numHitsToDestroyRock;
	    	rocklife4 = numHitsToDestroyRock;
	    	rocklife5 = numHitsToDestroyRock;
	
			if(currentLevel == 0)
			{
		        title = makeSprite(getImage("titlescreen.png"));
			    title.position((canvas.width() - title.width())/2, (canvas.height() - title.height())/2 - 10);
			    
			    enterToStart = makeSprite(getImage("start.png",255,255,255));
			    enterToStart.position((canvas.width() - enterToStart.width())/2, (canvas.height() + enterToStart.width() + title.height())/2);
			    //make this blinky!
			}
			else
			{
				openingLoop.stop();
			}
	
			
	    	//HUD
	    	display = makeSprite(getImage("hud.png", 200, 0, 0));
	        display.position(canvas.width()/2 - display.width()/2,
	                canvas.height() - display.height());
	        
	        // Reset start time
	        start_time = System.currentTimeMillis();
	        
	        //reset shield
	        shield = 3;
		}
		else
		{
			if(gameover)
			{
				title = makeSprite(getImage("gameover1.png"));
				title.position((canvas.width() - title.width())/2, (canvas.height() - title.height())/2 - 10);
			}
			else
			{
				System.out.println("win");
				title = makeSprite(getImage("win.png"));
				title.position((canvas.width() - title.width())/2, (canvas.height() - title.height())/2 - 10);
			}
		}

	}
    
    
    public void resetLaser()
    {
    	
    }
	
    public void draw()
    {
    	//draws images from background to foreground
    	
    	canvas.clear();
    	
    	portal.rotate(portalRotation);
		portal.draw();
		rock1.draw();
		rock2.draw();
		rock3.draw();
		rock4.draw();
		rock5.draw();
    	
    	ship.move();
		ship.rotate(shipRotation, shipCenterX, shipCenterY);
		ship.draw();
		
		//Draw enemy ships
		enemy1.move();
		enemy1.draw();
		enemy1.bounceIfCollidesWith(TOPEDGE,BOTTOMEDGE,LEFTEDGE,RIGHTEDGE, rock1, rock2, rock3, rock4, rock5, display, PIXELPERFECT);
		
		enemy2.move();
		enemy2.draw();
		enemy2.bounceIfCollidesWith(TOPEDGE,BOTTOMEDGE,LEFTEDGE,RIGHTEDGE, rock1, rock2, rock3, rock4, rock5, display, PIXELPERFECT);
		
		enemy3.move();
		enemy3.draw();
		enemy3.bounceIfCollidesWith(TOPEDGE,BOTTOMEDGE,LEFTEDGE,RIGHTEDGE, rock1, rock2, rock3, rock4, rock5, display, PIXELPERFECT);
		
		keepUnderMaxSpeed(ship, 10.0);
		rearFire.hide();
    	
	    ship.stopIfCollidesWith(TOPEDGE, BOTTOMEDGE, LEFTEDGE, RIGHTEDGE, enemy1, enemy2, PIXELPERFECT);
	    ship.stopIfCollidesWith(display, PIXELPERFECT);

		if(laserTimeOut)
		{
			gun = makeSprite(getImage("blank1.png", 255, 0, 0));
			ship.pin(gun, 85, 50);
			laserbeam = makeSprite(getImage("laser.png", 0, 0, 255));
			laserExists = false;
			laserTimeOut = false;
			laserRotation = 0;
		}
		
	    //~~~&&&~~~
		gun.draw();

		// laserbeam goes here.
		if(laserExists)
		{
			//laserRotation = shipRotation;
			laserbeam.move();
			laserbeam.rotate(laserRotation, laserCenterX, laserCenterY);
			laserbeam.draw();
		}
		
		// enemy laser beam
		if(enemyLaser1Exists)
		{
			enemyLaser1Rotation = shipRotation;
			enemyLaser1.move();
			enemyLaser1.rotate(enemyLaser1Rotation, enemyLaser1CenterX, enemyLaser1CenterY);
			
		}

		//Fire enemy laser
		if(enemyLaser1Exists == false)
		{
			enemyLaser1Exists = true;

			double thetaRad = 3.14159 * (double)enemyLaser1Rotation / 180.0;

			int x = enemy3.xPixel() + enemyLaser1CenterX;
			int y = enemy3.yPixel() + enemyLaser1CenterY;

			x += (int)(42 * Math.cos(thetaRad));
			y += (int)(42 * Math.sin(thetaRad));

			x -= 20;
			y -= 20;

			enemyLaser1.position(x, y);

			enemyLaser1.motion(20 * Math.cos(thetaRad),
						20 * Math.sin(thetaRad),
						ADD);
			
			startTimer("enemyLaser1Disappear",1350);//length of time laser is on screen - cool down time for gun...
		}
		
	    //~~~&&&~~~
	    
	    //Ship to Obstacle collision check
	    ship.checkIfCollidesWith(rock1, rock2, rock3, rock4, rock5, enemy1, enemy2, enemy3, PIXELPERFECT);
	    
	    if(ship.collided())
	   	{
	    	if(shield > 1)
	    		shield = shield - 1;
	    		
	    	else if(lives > 1)
	    	{
	    		//Take away a life and reset level
	    		lives = lives - 1;
	    		setupCurrentLevel();
	    	}
	    	else
	    	{	
	    		//Lives are depleted so end the game
	    		currentLevel = 0;
	    		lives = 3;
	    	 		
	    		gameover();
	    	    //title = makeSprite(getImage("gameover1.png"));
	    		//title.position((canvas.width() - title.width())/2, (canvas.height() - title.height())/2 - 10);
	    		display.hide();
	    	}
	   	}
	    
	    //Laser to obstacle collision check
	    laserbeam.stopIfCollidesWith(rock1,rock2,rock3,rock4,rock5, enemy1, enemy2, enemy3, PIXELPERFECT);
	    
	    laserbeam.checkIfCollidesWith(enemy1, PIXELPERFECT);
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	enemy1.hide();
	    	enemy1.motion(0, 0);
	    	enemy1.position(1000,1000);
	    }
	    
	    laserbeam.checkIfCollidesWith(enemy2, PIXELPERFECT);
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	enemy2.hide();
	    	enemy2.motion(0, 0);
	    	enemy2.position(1000,1000);
	    }
	    
	    laserbeam.checkIfCollidesWith(enemy3, PIXELPERFECT);
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	enemy3.hide();
	    	enemy3.motion(0, 0);
	    	enemy3.position(1000,1000);
	    }
	    
	    laserbeam.checkIfCollidesWith(rock1, PIXELPERFECT);
	    
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	rocklife1--;
	    	if(rocklife1<=0)
	    	{
	    		rock1.hide();
	    		rock1.position(1000, 1000);
	    	}
	    }
	    
	    laserbeam.checkIfCollidesWith(rock2, PIXELPERFECT);
	    
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	rocklife2--;
	    	if(rocklife2<=0)
	    	{
	    		rock2.hide();
	    		rock2.position(1000, 1000);
	    	}
	    }
	    
	    laserbeam.checkIfCollidesWith(rock3, PIXELPERFECT);
	    
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	rocklife3--;
	    	if(rocklife3<=0)
	    	{
	    		rock3.hide();
	    		rock3.position(1000, 1000);
	    	}
	    }
	    
	    laserbeam.checkIfCollidesWith(rock4, PIXELPERFECT);
	    
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	rocklife4--;
	    	if(rocklife4<=0)
	    	{
	    		rock4.hide();
	    		rock4.position(1000, 1000);
	    	}
	    }
	    
	    laserbeam.checkIfCollidesWith(rock5, PIXELPERFECT);
	    
	    if(laserbeam.collided())
	    {
	    	startTimer("laserDisappear",1);
	    	rocklife5--;
	    	if(rocklife5<=0)
	    	{
	    		rock5.hide();
	    		rock5.position(1000, 1000);
	    	}
	    }
	    
	    //level completion check
		ship.checkIfCollidesWith(portal, PIXELPERFECT);

		if(ship.collided())
		{
			success = false;
			if(currentLevel != 11)
			{
				currentLevel++;
			}
			
			ship.motion(0,0);
			setupCurrentLevel();
			//return;
		}
	    
    	if(currentLevel == 0)
    	{
    		title.draw();
    		enterToStart.draw();
    	}
    	
    	if(currentLevel == 11)
    	{
    		title.draw();
    	}
    	
    	//Check if Time has run out
    	
    	if(getRemainingTime() <= 0)
    	{
    		if(lives > 1)
	    	{
	    		//Take away a life and reset level
	    		lives = lives - 1;
	    		setupCurrentLevel();
	    	}
	    	else
	    	{	
	    		//Lives are depleted so end the game
	    		currentLevel = 0;
	    		lives = 3;
	    	 		
	    		gameover();
	    	    //title = makeSprite(getImage("gameover1.png"));
	    		//title.position((canvas.width() - title.width())/2, (canvas.height() - title.height())/2 - 10);
	    		display.hide();
	    	}
    	}
    	
    	//HUD
    	if(currentLevel > 0)
    	{
    		display.draw();
    		display.putText("Shield: ", 15, 15);
    		display.putText(shield, 60, 15);
    		
    		display.putText("Lives: ", 150, 15);
    		display.putText(lives, 190, 15);
    		
    		display.putText("Time: ", 400, 15);
    		display.putText(getRemainingTime(), 450, 15);
    		
    		display.putText("Level: ", 224, 15);
    		display.putText(currentLevel, 260, 15);
    		
    		//Track the mouse X and Y position for debugging and level design purposes
    		display.putText("X: ", 600, 15);
    		display.putText(mouse.x(), 650, 15);
    		
    		display.putText("Y: ", 700, 15);
    		display.putText(mouse.y(), 750, 15);
    	}
    }
    
    public void onKeyPress()
    {
    	//from the title screen to game
    	if(keyboard.key() == keyboard.ENTER && currentLevel == 0)
    	{
    		currentLevel = 1;
    		setupCurrentLevel();
    	}
    	
    	if(keyboard.key() == keyboard.K1 && currentLevel == 11)
    	{
    		gameover = false;
    		success = false;
    		currentLevel = 1;
    		setupCurrentLevel();
    	}
    	
    	if(keyboard.key() == keyboard.K2 && currentLevel == 11)
    	{
    		System.exit(0);
    	}
    	
    	if(keyboard.key() == keyboard.PERIOD)
    	{
    		currentLevel++;
    		setupCurrentLevel();
    	}
    	
		// w/up fires the main thruster.
		if(keyboard.key() == keyboard.UP || keyboard.key() == keyboard.W)
		{
			rearFire.show(); // show the player pretty flames.

			// accelerate the ship in the direction it's facing...
			// y accel proportional to sin (theta)
			// x accel proportional to cos (theta)

			// convert to radians...
			double thetaRad = 3.14159 * (double)shipRotation / 180.0;

			ship.motion(0.2 * Math.cos(thetaRad),
						0.2 * Math.sin(thetaRad),
						ADD);
			
			if(thrusterSoundActive == false)
			{
				thrusterSoundActive = true;
				thrusterSound.loop();
			}
		}
		else
		{
			thrusterSoundActive = false;
			thrusterSound.stop();
		}
		
		// s/down moves the ship to full stop.
		//if(keyboard.key() == keyboard.DOWN || keyboard.key() == keyboard.S)
		//{
			//ship.motion(0.8, 0.8, MULTIPLY);
		//}
		
		// a/left rotates ship left.
		if(keyboard.key() == keyboard.LEFT || keyboard.key() == keyboard.A)
		{
			shipRotation -= 5;
		}
		// d/right rotates ship right.
		if(keyboard.key() == keyboard.RIGHT || keyboard.key() == keyboard.D)
		{
			shipRotation += 5;
		}

		// keep rotation 0 <= x <= 359
		if(shipRotation < 0)
		{
			shipRotation += 360;
		}
		else if(shipRotation > 359)
		{
			shipRotation -= 360;
		}
		
		// space fires the projectile
		if (keyboard.key() == keyboard.SPACE && !laserExists)
		{
			laserExists = true;

			double thetaRad = 3.14159 * (double)shipRotation / 180.0;

			int x = ship.xPixel() + shipCenterX;
			int y = ship.yPixel() + shipCenterY;

			x += (int)(42 * Math.cos(thetaRad));
			y += (int)(42 * Math.sin(thetaRad));

			x -= 20;
			y -= 20;

			laserbeam.position(x, y);

			laserbeam.motion(20 * Math.cos(thetaRad),
						20 * Math.sin(thetaRad),
						ADD);
			
			startTimer("laserDisappear",1350);//length of time laser is on screen - cool down time for gun...
			laserRotation = shipRotation;
			
			laserSound.play();
		}	
    }
    
    public void laserDisappearTimer()
    {
    	stopTimer("laserDisappear");
    	laserbeam.hide();
    	laserExists = false;
    	//resetLaser();
    	laserTimeOut = true;
    }
    
    public void enemyLaser1DisappearTimer()
    {
    	stopTimer("enemyLaser1Disappear");
    	enemyLaser1.hide();
    	enemyLaser1Exists = false;
    	//resetLaser();
    	enemyLaser1TimeOut = true;
    }
    
	private void keepUnderMaxSpeed(Sprite s, double maxSpeed)
	{
		double xSpeed = s.xspeed();
		double ySpeed = s.yspeed();

		if ((xSpeed * xSpeed) + (ySpeed * ySpeed) > maxSpeed * maxSpeed)
		{
			// Object is moving too fast.
			// Scale its speed down while keeping the same direction.

			// derive theta via tan theta = opposite (y side) / adjacent (x side).
			double theta = Math.atan(ySpeed / xSpeed);

			s.motion(maxSpeed * Math.cos(theta), maxSpeed * Math.sin(theta));

		}
	}
	
	
	
	public int getRemainingTime()
	{
	    
	    // Get elapsed time in milliseconds
	    long elapsedTimeMillis = System.currentTimeMillis() - start_time;
	    
	    // Get elapsed time in seconds
	   int remaining_time = (int) (elapsedTimeMillis/1000);
	   
	   remaining_time = 30 - remaining_time;
	    
	   return remaining_time;
	}
	
}

/*
    public void titleScreen()
    {
    	Image bg = getImage("0.png");
        canvas.background(bg);

        title = makeSprite(getImage("spacemission.png",255,255,255));
	    title.position((canvas.width() - title.width())/2, (canvas.height() - title.height())/2);
	    
	    enterToStart = makeSprite(getImage("start.png",255,255,255));
	    enterToStart.position((canvas.width() - enterToStart.width())/2, (canvas.height() - enterToStart.width() - title.height())/2);
    }
 */
 //   	window.size(844,580);
